/**
 * Jugador.java
 *
 * Fecha de creación: May 5, 2012,5:01:44 PM
 *
 * Autor: José Ignacio Rivero Dávila
 */
package model;

import java.util.LinkedList;
import util.Movement;
import util.MovementNotAllowedException;
import util.Position;

public class Player extends AbstractModel{

    public static final boolean BLACK = true;
    public static final boolean RED = false;

    //private Node root;
    public LinkedList<Movement> calculatePossibleMoves(Board bd, boolean color) {
        boolean canJump = false;
        LinkedList<Movement> listMov = new LinkedList<Movement>();
        Checker[][] pos = bd.getPositions();
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                if (color == Player.BLACK && (pos[i][j] == Checker.BLACK || pos[i][j] == Checker.BLACKKING)) {
                    for (Movement mov : calculateMovesForChecker(i, j, null, pos[i][j], bd)) {
                        if (mov.isJump()) {
                            canJump = true;
                            listMov.addFirst(mov);
                        } else {
                            listMov.addLast(mov);
                        }
                    }
                } else if (color == Player.RED && (pos[i][j] == Checker.RED || pos[i][j] == Checker.REDKING)) {
                    for (Movement mov : calculateMovesForChecker(i, j, null, pos[i][j], bd)) {
                        if (mov.isJump()) {
                            canJump = true;
                            listMov.addFirst(mov);
                        } else {
                            listMov.addLast(mov);
                        }
                    }
                }
            }
        }
        int index = 0;
        while (canJump && listMov.size() > index && listMov.get(index).isJump()) {
            index++;
        }
        if (canJump && index < listMov.size()) {
            listMov = new LinkedList<Movement>(listMov.subList(0, index));
        }

        LinkedList<Movement> finalList = new LinkedList<Movement>();
        boolean isPart;
        Movement m1;
        Movement m2;
        for (int i = 0; i < listMov.size(); i++) {
            isPart = false;
            m1 = listMov.get(i);
            for (int j = 0; j < listMov.size(); j++) {
                m2 = listMov.get(j);
                if (i != j) {
                    if (m1.isPartOfJump(m2)) {
                        isPart = true;
                        break;
                    }
                }
            }
            if (!isPart) {
                finalList.add(m1);
            }
        }
        return finalList;
    }

    private LinkedList<Movement> calculateMovesForChecker(int i, int j, Movement jumpMov, Checker checkerType, Board bd) {
        LinkedList<Movement> movements = new LinkedList<Movement>();
        LinkedList<Movement> tempMovList;
        //Movement mov;
        int deltaI = (Checker.BLACK == checkerType) ? -1 : 1;
        int deltaJ = 1;
        Position iniPos = new Position(i, j);
        Position finalPos;
        int numLoops = (checkerType.equals(Checker.BLACKKING) || checkerType.equals(Checker.REDKING)) ? 4 : 2;
        for (int k = 0; k < numLoops; k++) {

            deltaJ *= -1;
            if (k == 2) {
                deltaI *= -1;
            }
            finalPos = new Position(i + deltaI, j + deltaJ);
            //mov = getMovementToIJ(iniPos, finalPos,jumpMov,checkerType, bd);
            tempMovList = getMovementToIJ(iniPos, finalPos, jumpMov != null ? jumpMov.clone() : null, checkerType, bd);
            for (Movement mov : tempMovList) {
                if (mov != null) {
                    if (mov.isJump()) {
                        movements.addFirst(mov);
                    } else {
                        movements.addLast(mov);
                    }
                }
            }

        }
        if (jumpMov != null) {
            movements.add(jumpMov);
        }
        return movements;
    }

    private LinkedList<Movement> getMovementToIJ(Position iniPos, Position finalPos, Movement jumpMov, Checker checkerType, Board bd) {
        Checker[][] pos = bd.getPositions();
        Movement mov = new Movement();
        LinkedList<Movement> jumpList = new LinkedList<Movement>();
        if (finalPos.i > 7 || finalPos.i < 0 || finalPos.j > 7 || finalPos.j < 0) {
            return jumpList;
        }
        if (pos[finalPos.i][finalPos.j].equals(Checker.EMPTY)) {
            if (jumpMov != null) {
                return jumpList;
            }
            mov.addPosition(iniPos);
            mov.addPosition(finalPos);
            mov.setIsJump(false);
            jumpList.add(mov);
        } else if (!checkerType.isOpponent(pos[finalPos.i][finalPos.j])) {
            if (jumpMov != null) {
                return jumpList;
            }
            //mov = null;
        } else {
            int deltaI = iniPos.i > finalPos.i ? -1 : 1;
            int deltaJ = iniPos.j > finalPos.j ? -1 : 1;
            jumpList = getJumpToIJ(iniPos, new Position(finalPos.i + deltaI, finalPos.j + deltaJ), jumpMov, checkerType, bd);
        }
        return jumpList;
    }

    private LinkedList<Movement> getJumpToIJ(Position iniPos, Position finalPos, Movement jumpMov, Checker checkerType, Board bd) {
        Checker[][] pos = bd.getPositions();
        LinkedList<Movement> jumpList = new LinkedList<Movement>();
        if (finalPos.i > 7 || finalPos.i < 0 || finalPos.j > 7 || finalPos.j < 0) {
            return jumpList;
        }
        if (!pos[finalPos.i][finalPos.j].equals(Checker.EMPTY)) {
            jumpMov = null;
        } else {
            if (jumpMov == null) {
                jumpMov = new Movement();
            }
            if (jumpMov.hasNoPositions()) {
                jumpMov.addPosition(iniPos);
            }
            jumpMov.addPosition(finalPos);
            jumpMov.setIsJump(true);
            //calculateMovesForChecker(finalPos.i, finalPos.i,jumpMov, checkerType, bd);
            Board aux = bd.clone();
            aux.getPositions()[iniPos.i][iniPos.j] = Checker.EMPTY;
            aux.getPositions()[(iniPos.i + finalPos.i) / 2][(iniPos.j + finalPos.j) / 2] = Checker.EMPTY;
            aux.getPositions()[finalPos.i][finalPos.j] = checkerType;
            jumpList = calculateMovesForChecker(finalPos.i, finalPos.j, jumpMov, checkerType, aux);
        }
        return jumpList;
    }

    private LinkedList<Board> createListOfBoardsWithPossibleMoves(Board bd, LinkedList<Movement> listMoves) {
        LinkedList<Board> listBd = new LinkedList<Board>();
        Board aux;
        for (Movement mov : listMoves) {
            aux = bd.clone();
            try {
                aux.move(mov);
                listBd.add(aux);
            } catch (MovementNotAllowedException e) {
                System.out.println(bd);
                e.printStackTrace();
                System.out.println(bd);
            }
        }
        return listBd;
    }

    public LinkedList<Board> createListOfBoardsWithPossibleMoves(Board bd, boolean color) {
        LinkedList<Movement> listMv = calculatePossibleMoves(bd, color);
        return createListOfBoardsWithPossibleMoves(bd, listMv);
    }

//    public static void main(String[] args) {
//        Board bd = new Board(FileReaderUtil.getBoardFromFile("board.txt"));
//        Player p = new Player();
//        System.out.println(bd.toString());
//        LinkedList<Movement> moves = p.calculatePossibleMoves(bd, Player.RED);
//        System.out.println("LISTADO DE MOVIMIENTOS");
//        for (Movement movement : moves) {
//            System.out.println(movement);
//        }
//
//        System.out.println("FIN LISTADO DE MOVIMIENTOS");
//        System.out.println("");
//
//        System.out.println("LISTADO DE LOS TABLEROS");
//        for (Board board : p.doMoves(bd, Player.RED)) {
//            System.out.println(board);
//
//        }
//    }
}
